#include <iostream>
#include <stdlib.h>
#include <time.h>
#include <vector>

#include "../common/ioUtils.h"
#include "../common/BigNumber.h"
#include "../common/bcd.h"
#include "../common/FastUInt.h"
#include "../common/GreatUInt.h"


using namespace std;
using namespace GiovaMath;
using namespace ZioUtils;

int main()
{
	const UInt NUM_SAMPLES = 1000;
	UInt i;
	Timer timer;

	srand((unsigned int)time(0));

	cout << endl << "Start Performance Test - Sample size: " << NUM_SAMPLES << endl;

	//Construction
	cout << endl << "Empty construction" << endl;

	timer.Start();
	vector<BigNumber> bigNumbers(NUM_SAMPLES);
	cout << "BigNumber: " << timer.TimeElapsedMicroSec() << endl;

	timer.Start();
	vector<bcd> bcds(NUM_SAMPLES);
	cout << "Bcd: " << timer.TimeElapsedMicroSec() << endl;

	timer.Start();
	vector<GreatUInt> greatUints(NUM_SAMPLES);
	cout << "GreatUInt: " << timer.TimeElapsedMicroSec() << endl;

	timer.Start();
	vector<FastUInt> fastUints(NUM_SAMPLES);
	cout << "FastUInt: " << timer.TimeElapsedMicroSec() << endl;

	//Assignement from UInt
	cout << endl << "Assignment from UInt Test" << endl;

	timer.Start();
	for(i=0; i<NUM_SAMPLES; ++i)
		bigNumbers[i] = static_cast<UInt>(rand());
	cout << "BigNumber: " << timer.TimeElapsedMicroSec() << endl;

	timer.Start();
	for(i=0; i<NUM_SAMPLES; ++i)
		bcds[i] = static_cast<UInt>(rand());
	cout << "bcd: " << timer.TimeElapsedMicroSec() << endl;

	timer.Start();
	for(i=0; i<NUM_SAMPLES; ++i)
		greatUints[i] = static_cast<UInt>(rand());
	cout << "GreatUInt: " << timer.TimeElapsedMicroSec() << endl;

	timer.Start();
	for(i=0; i<NUM_SAMPLES; ++i)
		fastUints[i] = static_cast<UInt>(rand());
	cout << "FastUInt: " << timer.TimeElapsedMicroSec() << endl;

	//small Sum
	cout << endl << "Small Sum Test" << endl;

	timer.Start();
	for(i=0; i<NUM_SAMPLES; ++i)
		bigNumbers[i] += bigNumbers[rand()%NUM_SAMPLES];
	cout << "BigNumber: " << timer.TimeElapsedMicroSec() << endl;

	timer.Start();
	for(i=0; i<NUM_SAMPLES; ++i)
		bcds[i] += bcds[rand()%NUM_SAMPLES];
	cout << "bcd: " << timer.TimeElapsedMicroSec() << endl;

	timer.Start();
	for(i=0; i<NUM_SAMPLES; ++i)
		greatUints[i] += greatUints[rand()%NUM_SAMPLES];
	cout << "GreatUInt: " << timer.TimeElapsedMicroSec() << endl;

	timer.Start();
	for(i=0; i<NUM_SAMPLES; ++i)
		fastUints[i] += fastUints[rand()%NUM_SAMPLES];
	cout << "FastUInt: " << timer.TimeElapsedMicroSec() << endl;

	//Mul
	cout << endl << "Mul Test" << endl;

	//timer.Start();
	//for(i=0; i<NUM_SAMPLES; ++i)
	//	bigNumbers[i] *= bigNumbers[rand()%NUM_SAMPLES];
	//cout << "BigNumber: " << timer.TimeElapsedMicroSec() << endl;

	//timer.Start();
	//for(i=0; i<NUM_SAMPLES; ++i)
	//	bcds[i] *= bcds[rand()%NUM_SAMPLES];
	//cout << "bcd: " << timer.TimeElapsedMicroSec() << endl;

	timer.Start();
	for(i=0; i<NUM_SAMPLES; ++i)
		greatUints[i] *= greatUints[rand()%NUM_SAMPLES];
	cout << "GreatUInt: " << timer.TimeElapsedMicroSec() << endl;

	timer.Start();
	for(i=0; i<NUM_SAMPLES; ++i)
		fastUints[i] *= fastUints[rand()%NUM_SAMPLES];
	cout << "FastUInt: " << timer.TimeElapsedMicroSec() << endl;

	//Big Sum
	cout << endl << "Big Sum Test" << endl;

	//timer.Start();
	//for(i=0; i<NUM_SAMPLES; ++i)
	//	bigNumbers[i] += bigNumbers[rand()%NUM_SAMPLES];
	//cout << "BigNumber: " << timer.TimeElapsedMicroSec() << endl;

	//timer.Start();
	//for(i=0; i<NUM_SAMPLES; ++i)
	//	bcds[i] += bcds[rand()%NUM_SAMPLES];
	//cout << "bcd: " << timer.TimeElapsedMicroSec() << endl;

	timer.Start();
	for(i=0; i<NUM_SAMPLES; ++i)
		greatUints[i] += greatUints[rand()%NUM_SAMPLES];
	cout << "GreatUInt: " << timer.TimeElapsedMicroSec() << endl;

	timer.Start();
	for(i=0; i<NUM_SAMPLES; ++i)
		fastUints[i] += fastUints[rand()%NUM_SAMPLES];
	cout << "FastUInt: " << timer.TimeElapsedMicroSec() << endl;


	//end of tests
	cout << "End of execution, press a key to exit!"<<endl;
	PressKey();
	return 0;
}